//-
// ==========================================================================
// Copyright (C) 1995 - 2006 Autodesk, Inc. and/or its licensors.  All 
// rights reserved.
//
// The coded instructions, statements, computer programs, and/or related 
// material (collectively the "Data") in these files contain unpublished 
// information proprietary to Autodesk, Inc. ("Autodesk") and/or its 
// licensors, which is protected by U.S. and Canadian federal copyright 
// law and by international treaties.
//
// The Data is provided for use exclusively by You. You have the right 
// to use, modify, and incorporate this Data into other products for 
// purposes authorized by the Autodesk software license agreement, 
// without fee.
//
// The copyright notices in the Software and this entire statement, 
// including the above license grant, this restriction and the 
// following disclaimer, must be included in all copies of the 
// Software, in whole or in part, and all derivative works of 
// the Software, unless such copies or derivative works are solely 
// in the form of machine-executable object code generated by a 
// source language processor.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND. 
// AUTODESK DOES NOT MAKE AND HEREBY DISCLAIMS ANY EXPRESS OR IMPLIED 
// WARRANTIES INCLUDING, BUT NOT LIMITED TO, THE WARRANTIES OF 
// NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR 
// PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE, OR 
// TRADE PRACTICE. IN NO EVENT WILL AUTODESK AND/OR ITS LICENSORS 
// BE LIABLE FOR ANY LOST REVENUES, DATA, OR PROFITS, OR SPECIAL, 
// DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES, EVEN IF AUTODESK 
// AND/OR ITS LICENSORS HAS BEEN ADVISED OF THE POSSIBILITY 
// OR PROBABILITY OF SUCH DAMAGES.
//
// ==========================================================================
//+


#ifndef _apiMeshShape
#define _apiMeshShape

///////////////////////////////////////////////////////////////////////////////
//
// apiMeshShape.h
//
// Implements a new type of shape node in maya called apiMesh.
//
// INPUTS
//     inputSurface    - input apiMeshData
//     outputSurface   - output apiMeshData
//     worldSurface    - array of world space apiMeshData, each element
//                       represents an istance of the shape
// OUTPUTS
//     mControlPoints  - inherited control vertices for the mesh. These values
//                       are tweaks (offsets) that will be applied to the
//                       vertices of the input shape.
//     bboxCorner1     - bounding box upper left corner
//     bboxCorner2     - bounding box lower right corner
//
////////////////////////////////////////////////////////////////////////////////

#include <maya/MPxSurfaceShape.h> 
#include <maya/MPxGeometryIterator.h> 
#include <maya/MTypeId.h> 
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MVectorArray.h>
#include <maya/MDoubleArray.h>
#include <maya/MSelectionList.h>
#include <maya/MSelectionMask.h>
#include <apiMeshGeom.h>
#include <apiMeshData.h>
#include <apiMeshIterator.h>

class MPointArray;

class apiMesh : public MPxSurfaceShape
{
public:
	apiMesh();
	virtual ~apiMesh(); 

    //////////////////////////////////////////////////////////
	//
	// Overrides
	//
    //////////////////////////////////////////////////////////

	// From MPxNode
	//
	virtual void			postConstructor();
    virtual MStatus   		compute( const MPlug& plug, MDataBlock& data );
	virtual bool			getInternalValue( const MPlug&,
											  MDataHandle&);
    virtual bool			setInternalValue( const MPlug&,
											  const MDataHandle&);
	virtual MStatus			connectionMade( const MPlug& plug,
											 const MPlug& otherPlug,
											 bool asSrc );
	virtual MStatus			connectionBroken( const MPlug& plug,
											 const MPlug& otherPlug,
											 bool asSrc );
	virtual MStatus			shouldSave( const MPlug& plug, bool& result );

	// Attribute to component (components)
	//
	virtual void			componentToPlugs( MObject &,
											  MSelectionList & ) const;
	virtual MatchResult		matchComponent( const MSelectionList& item,
											const MAttributeSpecArray& spec,
											MSelectionList& list );
	virtual bool			match(	const MSelectionMask & mask,
									const MObjectArray& componentList ) const;

	// Support deformers (components)
	//
	virtual MObject			createFullVertexGroup() const;
	virtual MObject 		localShapeInAttr() const;
 	virtual MObject 		localShapeOutAttr() const;
 	virtual MObject 		worldShapeOutAttr() const;
 	virtual MObject 		cachedShapeAttr() const;

	virtual MObject			geometryData() const;
	virtual void			closestPoint ( const MPoint & toThisPoint,
									MPoint & theClosestPoint,
									double tolerance ) const;

	// Support the translate/rotate/scale tool (components)
	//
	virtual void		    transformUsing( const MMatrix & mat,
						    			const MObjectArray & componentList );
	virtual void		    transformUsing( const MMatrix & mat,
											const MObjectArray & componentList,
											MPxSurfaceShape::MVertexCachingMode cachingMode,
											MPointArray* pointCache);
	virtual void			tweakUsing( const MMatrix & mat,
										const MObjectArray & componentList,
										MVertexCachingMode cachingMode,
										MPointArray* pointCache,
										MArrayDataHandle& handle );

	// Support the move tools normal/u/v mode (components)
	//
	virtual bool			vertexOffsetDirection( MObject & component,
                                                   MVectorArray & direction,
                                                   MVertexOffsetMode mode,
												   bool normalize );

	// Bounding box methods
	//
	virtual bool            isBounded() const;
	virtual MBoundingBox    boundingBox() const; 

	// Associates a user defined iterator with the shape (components)
	//
	virtual	MPxGeometryIterator*
							geometryIteratorSetup( MObjectArray&, MObject&,
												   bool forReadOnly = false );
	virtual bool			acceptsGeometryIterator( bool  writeable=true );
	virtual bool			acceptsGeometryIterator( MObject&, 
													 bool writeable=true,
													 bool forReadOnly = false);

    //////////////////////////////////////////////////////////
	//
	// Helper methods
	//
    //////////////////////////////////////////////////////////

	bool					hasHistory();

    MStatus 		  		computeInputSurface( const MPlug&, MDataBlock& );
    MStatus 		  		computeOutputSurface( const MPlug&, MDataBlock& );
    MStatus 		  		computeWorldSurface( const MPlug&, MDataBlock& );
	MStatus 		  		computeBoundingBox( MDataBlock& );

	MStatus					applyTweaks( MDataBlock&, apiMeshGeom* );

	bool					value( int pntInd, int vlInd, double & val ) const;
	bool					value( int pntInd, MPoint & val ) const;
	bool					setValue( int pntInd, int vlInd, double val );
	bool					setValue( int pntInd, const MPoint & val );

	MObject					meshDataRef();
	apiMeshGeom*			meshGeom();
	
	MObject					cachedDataRef();
	apiMeshGeom*			cachedGeom();

	MStatus					buildControlPoints( MDataBlock&, int count );
	void					verticesUpdated();

	static  void *          creator();
	static  MStatus         initialize();

public:
    //////////////////////////////////////////////////////////
    //
    // Attributes
    //
    //////////////////////////////////////////////////////////
    static  MObject         inputSurface;
    static  MObject         outputSurface;
    static  MObject         worldSurface;

	// used to support tweaking of points, the inputSurface attribute data is
	// transferred into the cached surface when it is dirty. The control points
	// tweaks are added into it there.
	//
    static  MObject         cachedSurface;

    static  MObject         bboxCorner1;
    static  MObject         bboxCorner2;
        
public: 
	static	MTypeId		id;

	bool fHasHistoryOnCreate;
};

#endif /* _apiMeshShape */
